home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CODECS.ZIP / codecs / english / codlzw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-13  |  12.7 KB  |  357 lines

  1. /* File: codlzw.c
  2.    Author: David Bourgin
  3.    Creation date: 25/3/95
  4.    Last update: 12/10/95
  5.    Purpose: Example of LZW encoding with a file source to compress.
  6. */
  7.  
  8. #include <stdio.h>
  9. /* For routines printf,fgetc and fputc. */
  10. #include <malloc.h>
  11. /* For routines malloc and free. */
  12. #include <stdlib.h>
  13. /* For routine exit. */
  14.  
  15. /* Error codes returned to the caller. */
  16. #define NO_ERROR       0
  17. #define BAD_FILE_NAME  1
  18. #define BAD_ARGUMENT   2
  19. #define BAD_MEM_ALLOC  3
  20.  
  21. /* Useful constants. */
  22. #define FALSE 0
  23. #define TRUE  1
  24.  
  25. /* Global variables. */
  26. FILE *source_file,*dest_file;
  27.  
  28.                              /* Being that fgetc=EOF only after an access
  29.                                 then 'byte_stored_status' is 'TRUE' if a byte has been stored by 'fgetc'
  30.                                 or 'FALSE' if there's no valid byte not handled in 'val_byte_stored' */
  31. int byte_stored_status=FALSE;
  32. int byte_stored_val;
  33.  
  34. /* Pseudo procedures */
  35. #define end_of_data()  (byte_stored_status?FALSE:!(byte_stored_status=((byte_stored_val=fgetc(source_file))!=EOF)))
  36. #define read_byte()  (byte_stored_status?byte_stored_status=FALSE,(unsigned char)byte_stored_val:(unsigned char)fgetc(source_file))
  37. #define write_byte(byte)  ((void)fputc((byte),dest_file))
  38.  
  39. unsigned long int val_to_read=0,
  40.                   val_to_write=0;
  41. unsigned char bit_counter_to_read=0,
  42.               bit_counter_to_write=0;
  43.  
  44. typedef struct s_dic_val { unsigned int character;
  45.                            unsigned int code;
  46.                            struct s_dic_val *left_ptr,
  47.                                             *right_ptr;
  48.                          } t_dic_val,*p_dic_val;
  49. #define CHAR_DIC_VAL(ptr_dic)  ((*(ptr_dic)).character)
  50. #define CODE_DIC_VAL(ptr_dic)  ((*(ptr_dic)).code)
  51. #define PLEFT_DIC_VAL(ptr_dic)  ((*(ptr_dic)).left_ptr)
  52. #define PRIGHT_DIC_VAL(ptr_dic)  ((*(ptr_dic)).right_ptr)
  53.  
  54. #define TYPE_GIF_ENCODING
  55. /* Enforces including marker codes initialization_code et end_information_code.
  56.    To invalid this option, set the line #define... in comments. */
  57.  
  58. unsigned int index_dic;
  59. /* Word counter already known in the dictionary. */
  60. unsigned char bit_counter_encoding;
  61. /* Bit counter in the encoding. */
  62.  
  63. #define EXP2_DIC_MAX  12
  64. /* 2^EXP2_DIC_MAX gives the maximum word counter in the dictionary during *all* the compressions.
  65.    Possible values: 3 to 25.
  66.    Attention: Beyond 12, you can have some errors of memory allocation
  67.    depending on your compiler and your computer. */
  68. unsigned int index_dic_max;
  69. /* index_dic_max gives the maximum word counter in the dictionary during *one* compression.
  70.    This constant is restricted to the range of end_information_code to 2^EXP2_DIC_MAX. */
  71. unsigned char input_bit_counter,
  72. /* Bit counter for each data in input.
  73.    With input_bit_counter=1, we can compress/decompress monochrome pictures
  74.    and with input_bit_counter=8, we can handle 256-colors pictures or any kind of files. */
  75.               bit_counter_min_encoding;
  76. /* Bit counter to encode 'initialization_code'. */
  77. unsigned int initialization_code;
  78. unsigned int end_information_code;
  79. /* initialization_code and end_information_code are both consecutive
  80.    coming up just after the last known word in the initial dictionary. */
  81.  
  82. p_dic_val dictionary[1<<EXP2_DIC_MAX];
  83.  
  84. void init_dictionary1()
  85. /* Returned parameters: None.
  86.    Action: First initialization of the dictionary when we start an encoding.
  87.    Errors: None if there is enough room.
  88. */
  89. { register unsigned int i;
  90.  
  91.   index_dic_max=1<<12;       /* Attention: Possible values: 2^3 to 2^EXP2_DIC_MAX. */
  92.   input_bit_counter=8;       /* Attention: Possible values: 1 to EXP2_DIC_MAX-1
  93.                                 (usually, for pictures, set up to 1, or 4, or 8, in the case
  94.                                 of monochrome, or 16-colors, or 256-colors picture). */
  95.   if (input_bit_counter==1)
  96.      bit_counter_min_encoding=3;
  97.   else bit_counter_min_encoding=input_bit_counter+1;
  98.   initialization_code=1<<(bit_counter_min_encoding-1);
  99. #ifdef TYPE_GIF_ENCODING
  100.   end_information_code=initialization_code+1;
  101. #else
  102.   end_information_code=initialization_code-1;
  103. #endif
  104.   for (i=0;i<=end_information_code;i++)
  105.       { if ((dictionary[i]=(p_dic_val)malloc(sizeof(t_dic_val)))==NULL)
  106.            { while (i)
  107.              { i--;
  108.                free(dictionary[i]);
  109.              }
  110.              exit(BAD_MEM_ALLOC);
  111.            }
  112.         CHAR_DIC_VAL(dictionary[i])=i;
  113.         CODE_DIC_VAL(dictionary[i])=i;
  114.         PLEFT_DIC_VAL(dictionary[i])=NULL;
  115.         PRIGHT_DIC_VAL(dictionary[i])=NULL;
  116.       }
  117.   for (;i<index_dic_max;i++)
  118.       dictionary[i]=NULL;
  119.   index_dic=end_information_code+1;
  120.   bit_counter_encoding=bit_counter_min_encoding;
  121. }
  122.  
  123. void init_dictionary2()
  124. /* Returned parameters: None.
  125.    Action: Initialization of the dictionary during the encoding.
  126.    Errors: None.
  127. */
  128. { register unsigned int i;
  129.  
  130.   for (i=0;i<index_dic_max;i++)
  131.       { PLEFT_DIC_VAL(dictionary[i])=NULL;
  132.         PRIGHT_DIC_VAL(dictionary[i])=NULL;
  133.       }
  134.   index_dic=end_information_code+1;
  135.   bit_counter_encoding=bit_counter_min_encoding;
  136. }
  137.  
  138. void remove_dictionary()
  139. /* Returned parameters: None.
  140.    Action: Removes the dictionary used for the decoding from the dynamical memory.
  141.    Errors: None.
  142. */
  143. { register unsigned int i;
  144.  
  145.   for (i=0;(i<index_dic_max)&&(dictionary[i]!=NULL);i++)
  146.       free(dictionary[i]);
  147. }
  148.  
  149. p_dic_val find_node(current_node,symbol)
  150. /* Returned parameters: Returns a node in the tree of the dictionary.
  151.    Action: Looks for 'symbol' from 'current_node'.
  152.    This research is made from the left pointer of 'current_node'
  153.    (if the left pointer wasn't equal to NULL) and then move to all the right
  154.    pointers until we reach the node containing 'symbol' or the last node which
  155.    right pointer is NULL.
  156.    Errors: If the symbol has not been found out, (current_node=returned node) or (CHAR_DIC_VAL(returned node)#symbol).
  157.    The 'current_node' given to this routine must never be equal to NULL.
  158. */
  159. p_dic_val current_node;
  160. unsigned int symbol;
  161. { p_dic_val new_node;
  162.  
  163.   if (PLEFT_DIC_VAL(current_node)==NULL)
  164.      return current_node;
  165.   else { new_node=PLEFT_DIC_VAL(current_node);
  166.          while ((CHAR_DIC_VAL(new_node)!=symbol)&&(PRIGHT_DIC_VAL(new_node)!=NULL))
  167.                new_node=PRIGHT_DIC_VAL(new_node);
  168.          return new_node;
  169.        }
  170. }
  171.  
  172. void add_node(current_node,new_node,symbol)
  173. /* Returned parameters: None.
  174.    Action: Creates a new_node in the tree of dictionary.
  175.    The summoning of this routine is normally done after a call to to find_node.
  176.    Errors: None.
  177. */
  178. p_dic_val current_node,new_node;
  179. unsigned int symbol;
  180. { if (dictionary[index_dic]==NULL)
  181.      { if ((dictionary[index_dic]=(p_dic_val)malloc(sizeof(t_dic_val)))==NULL)
  182.           { remove_dictionary();
  183.             exit(BAD_MEM_ALLOC);
  184.           }
  185.        CODE_DIC_VAL(dictionary[index_dic])=index_dic;
  186.        PLEFT_DIC_VAL(dictionary[index_dic])=NULL;
  187.        PRIGHT_DIC_VAL(dictionary[index_dic])=NULL;
  188.      }
  189.   CHAR_DIC_VAL(dictionary[index_dic])=symbol;
  190.   if (current_node==new_node)
  191.      PLEFT_DIC_VAL(new_node)=dictionary[index_dic];
  192.   else PRIGHT_DIC_VAL(new_node)=dictionary[index_dic];
  193.   index_dic++;
  194.   if (index_dic==(1 << bit_counter_encoding))
  195.      bit_counter_encoding++;
  196. }
  197.  
  198. #define dictionary_sature()  (index_dic==index_dic_max)
  199.  
  200. void write_code_lr(value)
  201. /* Returned parameters: None.
  202.    Action: Sends the value coded on 'bit_counter_encoding' bits in the stream of output codes.
  203.    The bits are stored from right to left. Example: aaabbbbcccc is written:
  204.    Bits     7 6 5 4 3 2 1 0
  205.    Byte 1   a a a b b b b c
  206.    Byte 2   c c c ? ? ? ? ?
  207.    Errors: An input/output error could disturb the running of the program.
  208. */
  209. unsigned int value;
  210. { val_to_write=(val_to_write << bit_counter_encoding) | value;
  211.   bit_counter_to_write += bit_counter_encoding;
  212.   while (bit_counter_to_write>=8)
  213.         { bit_counter_to_write -= 8;
  214.           write_byte((unsigned char)(val_to_write >> bit_counter_to_write));
  215.           val_to_write &= ((1<< bit_counter_to_write)-1);
  216.         }
  217. }
  218.  
  219. void complete_encoding_lr()
  220. /* Returned parameters: None.
  221.    Action: Adds 0-bits to the last byte to write, if any.
  222.    This procedure is to be considered with the procedure write_code_lr.
  223.    Errors: An input/output error could disturb the running of the program.
  224. */
  225. { if (bit_counter_to_write>0)
  226.      write_byte((unsigned char)(val_to_write << (8-bit_counter_to_write)));
  227.   val_to_write=bit_counter_to_write=0;
  228. }
  229.  
  230. void write_code_rl(value)
  231. /* Returned parameters: None.
  232.    Action: Sends the value coded on 'bit_counter_encoding' bits in the stream of output codes.
  233.    The bits are stored from right to left. Example: aaabbbbcccc is written:
  234.    Bits     7 6 5 4 3 2 1 0
  235.    Byte 1   c b b b b a a a
  236.    Byte 2   ? ? ? ? ? c c c
  237.    Errors: An input/output error could disturb the running of the program.
  238. */
  239. unsigned int value;
  240. { val_to_write |= ((unsigned long int)value) << bit_counter_to_write;
  241.   bit_counter_to_write += bit_counter_encoding;
  242.   while (bit_counter_to_write>=8)
  243.         { bit_counter_to_write -= 8;
  244.           write_byte((unsigned char)(val_to_write&0xFF));
  245.           val_to_write = (val_to_write>>8)&((1<< bit_counter_to_write)-1);
  246.         }
  247. }
  248.  
  249. void complete_encoding_rl()
  250. /* Returned parameters: None.
  251.    Action: Adds 0-bits to the last byte to write, if any.
  252.    This procedure is to be considered with the procedure write_code_rl.
  253.    Errors: An input/output error could disturb the running of the program.
  254. */
  255. { if (bit_counter_to_write>0)
  256.      write_byte((unsigned char)val_to_write);
  257.   val_to_write=bit_counter_to_write=0;
  258. }
  259.  
  260. unsigned int read_input()
  261. /* Returned parameters: None.
  262.    Action: Reads input_bit_counter via the function 'read_byte'.
  263.    Errors: An input/output error could disturb the running of the program.
  264. */
  265. { unsigned int read_code;
  266.  
  267.   while (bit_counter_to_read<input_bit_counter)
  268.         { val_to_read=(val_to_read<<8)|read_byte();
  269.           bit_counter_to_read += 8;
  270.         }
  271.   bit_counter_to_read -= input_bit_counter;
  272.   read_code=val_to_read>>bit_counter_to_read;
  273.   val_to_read &= ((1<<bit_counter_to_read)-1);
  274.   return read_code;
  275. }
  276.  
  277. #define end_input()  ((bit_counter_to_read<input_bit_counter)&&end_of_data())
  278.  
  279. void lzwencoding()
  280. /* Returned parameters: None.
  281.    Action: Compresses with LZW method all bytes read by the function 'read_input'.
  282.    Errors: An input/output error could disturb the running of the program.
  283. */
  284. { p_dic_val current_node,new_node;
  285.   unsigned int symbol;
  286.  
  287.   if (!end_input())
  288.      { init_dictionary1();
  289. #ifdef TYPE_GIF_ENCODING
  290.        write_code_lr(initialization_code);
  291. #endif
  292.        current_node=dictionary[read_input()];
  293.        while (!end_input())
  294.              { symbol=read_input();
  295.                new_node=find_node(current_node,symbol);
  296.                if ((new_node!=current_node)&&(CHAR_DIC_VAL(new_node)==symbol))
  297.                   current_node=new_node;
  298.                else { write_code_lr(CODE_DIC_VAL(current_node));
  299.                       add_node(current_node,new_node,symbol);
  300.                       if dictionary_sature()
  301.                          {
  302. #ifdef TYPE_GIF_ENCODING
  303.                            write_code_lr(initialization_code);
  304. #endif
  305.                            init_dictionary2();
  306.                          }
  307.                       current_node=dictionary[symbol];
  308.                     }
  309.              }
  310.        write_code_lr(CODE_DIC_VAL(current_node));
  311. #ifdef TYPE_GIF_ENCODING
  312.        write_code_lr(end_information_code);
  313. #endif
  314.        complete_encoding_lr();
  315.        remove_dictionary();
  316.      }
  317. }
  318.  
  319. void aide()
  320. /* Returned parameters: None.
  321.    Action: Displays the help of the program and then stops its running.
  322.    Errors: None.
  323. */
  324. { printf("This utility enables you to compress a file by using LZW method\n");
  325.   printf("as given 'La Video et Les Imprimantes sur PC'\n");
  326.   printf("\nUse: codlzw source target\n");
  327.   printf("source: Name of the file to compress\n");
  328.   printf("target: Name of the compressed file\n");
  329. }
  330.  
  331. int main(argc,argv)
  332. /* Returned parameters: Returns an error code (0=None).
  333.    Action: Main procedure.
  334.    Errors: Detected, handled and an error code is returned, if any.
  335. */
  336. int argc;
  337. char *argv[];
  338. { if (argc!=3)
  339.      { aide();
  340.        exit(BAD_ARGUMENT);
  341.      }
  342.   else if ((source_file=fopen(argv[1],"rb"))==NULL)
  343.           { aide();
  344.             exit(BAD_FILE_NAME);
  345.           }
  346.        else if ((dest_file=fopen(argv[2],"wb"))==NULL)
  347.                { aide();
  348.                  exit(BAD_FILE_NAME);
  349.                }
  350.             else { lzwencoding();
  351.                    fclose(source_file);
  352.                    fclose(dest_file);
  353.                  }
  354.   printf("Execution of codlzw completed.\n");
  355.   return (NO_ERROR);
  356. }
  357.